package com.me.springsimple.security.service.impl;

import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.AliasToEntityMapResultTransformer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Service;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import com.me.springsimple.entity.EmpEntity;
import com.me.springsimple.security.service.SecurityService;

@Service
public class SecurityServiceImpl implements SecurityService{

	@Autowired
	private HibernateTemplate hibernateTemplate;
	
	private String algorithm = "AES";
	private String securityKey = "RMS";
	private boolean keyAndCipherInit = false;
	private Cipher cipher = null;
	private SecretKeySpec secretKeySpec = null;
	
	@Override
	public String encodePassword(String encodePassword) {
		String encryptedText = "";
		try {
			if (!isKeyAndCipherInit()) {
				initKeyAndCipher();
			}
			cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
			byte[] plainTextByte = encodePassword.getBytes("UTF-8");
			byte[] encryptedByte = cipher.doFinal(plainTextByte);
			BASE64Encoder encoder = new BASE64Encoder();
			encryptedText = encoder.encode(encryptedByte);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return encryptedText;
	}

	@Override
	public String decodePassword(String decodePassword) {
		String plainTextPassword = "";
		try {
			if (!isKeyAndCipherInit()) {
				initKeyAndCipher();
			}
			cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
			BASE64Decoder decode = new BASE64Decoder();
			byte[] encryptedByte = decode.decodeBuffer(decodePassword);
			byte[] plainTextByte = cipher.doFinal(encryptedByte);
			plainTextPassword = new String(plainTextByte);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return plainTextPassword;
	}
	
	private void initKeyAndCipher() throws NoSuchAlgorithmException, NoSuchPaddingException, IOException {
		if (secretKeySpec == null) {
			MessageDigest sha = MessageDigest.getInstance("SHA-1");
			byte[] keyBytes = sha.digest(securityKey.getBytes("UTF-8"));
			keyBytes = Arrays.copyOf(keyBytes, 16);
			secretKeySpec = new SecretKeySpec(keyBytes, algorithm);
		}
		if (cipher == null) {
			cipher = Cipher.getInstance(algorithm);
		}
		keyAndCipherInit = true;
	}
	
	public boolean isKeyAndCipherInit() {
		return keyAndCipherInit;
	}

	@Override
	public List<Map<String, Object>> findFromNego() {
		DetachedCriteria criteria = DetachedCriteria.forClass(EmpEntity.class,"emp");
		
		//criteria.setResultTransformer(Transformers.aliasToBean(tets.class));
		criteria.createAlias("emp.work", "work");
		ProjectionList projectionList = Projections.projectionList();
		projectionList.add(Projections.property("name"));
		projectionList.add(Projections.property("work.work"),"work");
		
		criteria.setProjection(projectionList);
		criteria.add( Restrictions.eq("work.workid", 2));
		criteria.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);

		List<Map<String,Object>> listMap = hibernateTemplate.findByCriteria(criteria);
		
		for(Map<String,Object> m  : listMap){
			System.out.println(m.toString());
		}
		

		return listMap;
	}

	@Override
	public List<EmpEntity> findUser(String username) {
		DetachedCriteria criteria = DetachedCriteria.forClass(EmpEntity.class,"emp");
		criteria.add(Restrictions.eq("emp.username", username));
		//criteria.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);

		return hibernateTemplate.findByCriteria(criteria);
	}

}
